package fregat.connector.base;

import java.util.Enumeration;
import java.util.Hashtable;

import fregat.connector.ConnectorService;

/**
 * Used to filter received messages.
 *
 * @author Alexander Mann <br><b><i>ECO_L O G</i> &nbsp Logistiksysteme GmbH</b>
 * @version 1.0
 */
public class DataFilter {
  private Hashtable rules; // table with filter rules
  private boolean filterAll; // flag, that all messages should be blocked

  /**
   * Block all messages
   */
  public void filterAll() {
    filterAll = true;
  }

  /**
   * Adds a filter rule. A rule is specified with three parameter
   * (eg. 14,A is a rule that the character at position 14 is an 'A')
   *
   * @param position Position in data string
   * @param value    Value to compare to
   */
  public void addRule(int position, String value) {
    String key = position + value;
    if (rules == null) {
      rules = new Hashtable();
    }
    // convert non-printable characters
    value = ASCIIProtocol.convertCharacters(value);
    Rule rule = (Rule) rules.get(key);
    if (rule == null) {
      rule = new Rule(position, value);
      rules.put(key, rule);
    }
  }

  /**
   * Removes a filter rule.
   *
   * @param position Position in data string
   * @param value    Value to compare to
   */
  public void removeRule(int position, String value) {
    if (rules != null) {
      rules.remove(position + value);
    }
  }

  /**
   * Checks whether the given data should be further processed. Checks if the
   * given data matches one of the specified filter rules.
   *
   * @param data Data to be filtered
   * @param name Name of worker
   * @return True, when data should be processed (no rule matches)
   */
  public boolean process(String data, String name) {
    if (filterAll) {
      return false;
    }

    Enumeration e = rules.elements();
    boolean block = false;

    while (e.hasMoreElements() && !block) {
      Rule rule = (Rule) e.nextElement();
      try {
        String value = data.substring(rule.start, rule.end);
        block = (value.equals(rule.value));

        String key = "DataFilter_process_" + (block ? 4 : 3);
        ConnectorService.note(name + ", " + ConnectorService.resource.getString("DataFilter_process_2")
          .replaceFirst("%1", value)
          .replaceFirst("%2", Integer.toString(rule.start + 1))
          .replaceFirst("%3", rule.toString()) + " " +
          ConnectorService.resource.getString(key));

      } catch (Exception ex) {
        ConnectorService.warn("'" + rule + "'-" +
          ConnectorService.resource.getString("DataFilter_process_1") +
          " '" + data + "'");
      }
    }
    return !block;
  }

  /**
   * Filter rule data
   */
  private class Rule {
    int start;
    int end;
    String value;

    public Rule(int position, String value) {
      this.start = position - 1;
      this.end = start + value.length();
      this.value = value;
    }

    public String toString() {
      return (start + 1) + "," + value;
    }
  }
}
